package fr.coding.kata.nantes.fizzbuzz.michel;

import fr.coding.kata.nantes.fizzbuzz.commons.FizzBuzzInterface;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

public class PlayfullCountingSystem implements FizzBuzzInterface {
    public static final String EMPTY = "";
    public static final String EOL = System.getProperty("line.separator");

    private final LinkedHashMap<Integer, String> orderedMapping = new LinkedHashMap<Integer, String>();
    private ApiLevel apiLevel;

    /**
     *
     */
    public PlayfullCountingSystem() {
        this(ApiLevel.ONE);
    }


    /**
     * @param apiLevel
     */
    public PlayfullCountingSystem(ApiLevel apiLevel) {
        this.apiLevel = apiLevel;
    }

    /**
     * Add a mapping from a multiple to a word.
     *
     * @param multiple
     * @param word
     */
    public void addMapping(int value, String word) {
        orderedMapping.put(value, word);
    }

    protected static boolean isMultipleOfOrContains(int number, int multiple) {
        return isMultipleOf(number, multiple)
                || String.valueOf(number).contains(String.valueOf(multiple));
    }

    protected static boolean isMultipleOf(int number, int multiple) {
        return number % multiple == 0;
    }

    public String responseFor(int value) {
        String response = EMPTY;
        Set<Entry<Integer, String>> orderedEntrySet = orderedMapping.entrySet();
        for (Entry<Integer, String> entry : orderedEntrySet) {
            boolean isMagicNumber = isMagicNumber(value, entry);
            if (isMagicNumber)
                response += entry.getValue();
        }
        if (EMPTY.equals(response))
            response = String.valueOf(value);
        return response;
    }

    protected boolean isMagicNumber(int value, Entry<Integer, String> entry) {
        boolean isMagicNumber = false;
        switch (apiLevel) {
            case ONE:
                isMagicNumber = isMultipleOf(value, entry.getKey());
                break;
            case TWO:
                isMagicNumber = isMultipleOfOrContains(value, entry.getKey());
                break;
            default:
                throw new UnsupportedOperationException(
                        "This API level is  not supported");
        }
        return isMagicNumber;
    }

    public List<String> listValues(int from, int to) {
        List<String> respons = new ArrayList<String>();
        for (int currentInputValue = from; currentInputValue <= to; currentInputValue++) {
            String currentOutputValue = responseFor(currentInputValue);
            respons.add(currentOutputValue);
        }
        return respons;
    }

    public String call() {
        List<String> listValues = listValues(1, 100);
        StringBuilder s = new StringBuilder(300);
        for (String string : listValues) {
            s.append(string);
            s.append(EOL);
        }
        return s.toString();
    }
}
